package study2018.com.xtianzhuang.www.luncene;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

public class FileIndexWriter {
	public static void main(String[] args) throws Exception {
		/* 指明要索引文件夹的位置,可以根据自己的需要进行设定。这里是C盘的source文件夹下 */
		// D:\study\luncene\index
		File fileDir = new File("D:\\study\\luncene\\source");
		/* 这里放索引文件的位置 */
		File indexDir = new File("D:\\study\\luncene\\index");
		// 1、创建Directory
		Directory dir = FSDirectory.open(indexDir); // 索引文件的保存位置

		// 2、创建Analyzer
		// 分析器，选择“标准分析器”,参数代表当前使用的Lucene版本(jar包),也有人写Version.LUCENE_CURRENT
		// StandardAnalyzer可以做如下功能:
		// 1、对原有句子按照空格进行了分词 ;
		// 2、所有的大写字母都可以能转换为小写的字母 ;
		// 3、可以去掉一些没有用处的单词，例如"is","the","are"等单词，也删除了所有的标点。
		Analyzer luceneAnalyzer = new StandardAnalyzer(Version.LUCENE_36);

		// 3、创建IndexWriter
		// 创建IndexWriter,索引的核心组件。在Lucene3.X版本后，在创建时需要用到IndexWriterConfig配置类对IndexWriter的配置。
		// 第一个参数是目前的版本，第二个参数是词法分析器Analyzer。
		IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_36, luceneAnalyzer);
		// setOpenMode，设置存放索引的文件夹将以覆盖或者新建的方式建立，有下面几个选项：
		// APPEND：总是追加，可能会导致错误，索引还会重复，导致返回多次结果;
		// CREATE：清空重建（推荐）;
		// CREATE_OR_APPEND【默认】：创建或追加。
		iwc.setOpenMode(OpenMode.CREATE);
		IndexWriter indexWriter = new IndexWriter(dir, iwc);

		File[] textFiles = fileDir.listFiles();
		// 用于计算时间
		long startTime = System.currentTimeMillis();

		// 增加document(txt格式)到索引去
		for (int i = 0; i < textFiles.length; i++) {
			if (textFiles[i].isFile() && textFiles[i].getName().endsWith(".txt")) {
				System.out.println("File " + textFiles[i].getCanonicalPath() + "正在被索引..");
				String temp = FileReaderAll(textFiles[i].getCanonicalPath(), "GBK");
				System.out.println(temp);
				// 打印文件的内容
				// 申请一个document对象，代表一些域Field的集合。这个类似于数据库中的表。
				// Document相当于一个要进行索引的单元，任何可以想要被索引的文件都必须转化为Document对象才能进行索引。
				// 4、创建Document对象
				Document document = new Document();
				// Field：字段,文档中的一个具体的域，如文档创建时间,作者,内容等。
				// 其组成部分包括type(域的类型),name(域的名称),fieldsData(域的值),boost(加强因子).
				// Field.Store.YES:存储域值，适用于显示搜索结果的字段 — 例如，文件路径和 URL。;
				// Field.Index.NO:使对应的域值不被搜索，适用于未搜索的字段 — 仅用于存储字段，比如文件路径。
				// Field.Index.ANALYZED 用于字段索引和分析 — 例如，电子邮件消息正文和标题。
				// 路径
				Field FieldPath = new Field("path", textFiles[i].getPath(), Field.Store.YES, Field.Index.NO);
				// 内容
				Field FieldBody = new Field("content", temp, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS);
				// 5、为Document添加Field
				document.add(FieldPath);
				document.add(FieldBody);
				// 6、通过IndexWriter添加文档到索引中
				indexWriter.addDocument(document); // 把doc对象加入到索引创建中。
			}
		}
		indexWriter.close(); // 关闭IndexWriter,提交创建内容。

		// 测试一下索引的时间
		long endTime = System.currentTimeMillis();
		System.out.println("建立目录" + fileDir.getPath() + " 下所有文档的索引，总共消耗 " + (endTime - startTime) + " 毫秒!");
	}

	public static String FileReaderAll(String FileName, String charset) throws IOException {
		BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(FileName), charset));
		String line = new String();
		String temp = new String();

		while ((line = reader.readLine()) != null) {
			temp += line;
		}
		reader.close();
		return temp;
	}
}
